package com.coocaa.ops.api.v1.internal.service;

import com.coocaa.ops.api.base.cache.enums.InterfaceCacheMethodEnum;
import com.coocaa.ops.api.base.cache.properties.CacheProperties;
import com.coocaa.ops.common.core.base.model.R;
import com.coocaa.ops.common.core.biz.cache.constant.CacheEnvConstants;
import com.coocaa.ops.common.tool.base.InstanceUtil;
import com.coocaa.ops.common.tool.cache.impl.MyCacheServiceImpl;
import com.coocaa.ops.common.tool.cache.model.ScanResultInfo;
import com.coocaa.ops.common.tool.cache.util.ZipUtil;
import com.coocaa.ops.common.tool.exception.ExceptionUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.*;

/**
 * @author bijiahao
 * @date : 2019/6/21.
 * @description 提供给管理后台-进行缓存的查询等操作
 */
@Slf4j
@Service
public class CacheInternalOpsServiceImpl implements ICacheInternalOpsService {
    @Autowired
    private MyCacheServiceImpl myCacheService;

    @Override
    public R listKeyType() {
        InterfaceCacheMethodEnum[] methodEnums = InterfaceCacheMethodEnum.values();
        List<Map<String, String>> types = new ArrayList<>();

        for (InterfaceCacheMethodEnum methodEnum : methodEnums) {
            Map<String, String> type = InstanceUtil.newHashMap(1);
            type.put(methodEnum.getCacheMethod(), methodEnum.getDesc());

            types.add(type);
        }
        return R.ok(types);
    }

    @Override
    public R listKey(String key, String cacheEnv, Integer page, Integer pageSize, Integer matchPattern) {
        if (page < 1) {
            page = 1;
        }
        if (pageSize == null || pageSize < 1) {
            pageSize = 15;
        }
        String pattern = Objects.equals(matchPattern, 1) ? "*" + key + "*" : key;
        RedisTemplate<String, Serializable> redisTemplate = getRedisTemplate(cacheEnv);
        ScanResultInfo keys = myCacheService.scanKeysByPage(pattern, redisTemplate, page, pageSize);
        return R.ok(keys.getTotal(), keys.getKeys());
    }

    @Override
    public R listKeyV2(String key, String cacheEnv, Integer scanCount, Integer pageSize, Integer matchPattern) {
        String pattern = Objects.equals(matchPattern, 1) ? "*" + key + "*" : key;
        RedisTemplate<String, Serializable> redisTemplate = getRedisTemplate(cacheEnv);
        Set<String> keys = myCacheService.scanKeys(pattern, scanCount, pageSize, redisTemplate);
        if (key == null) {
            keys = Collections.emptySet();
        }
        return R.ok(keys.size(), keys);
    }


    @Override
    public R getValByKey(String key, String cacheEnv) {
        Object value = this.get(key, cacheEnv);
        return R.ok().data(value);
    }

    @Override
    public R delByKey(String[] keys, Integer matchPattern, String cacheEnv) {
        long count = 0;
        if (Objects.equals(matchPattern, 1) && CacheProperties.Constants.BATCH_DEL) {
            for (String key : keys) {
                long temp = myCacheService.deletePattern(key + "*");
                count += temp;
            }
        } else {
            for (String key : keys) {
                boolean res = this.delete(key, cacheEnv);
                if (res) {
                    count++;
                }
            }
        }
        return R.ok().data("清理数量: " + count);
    }

    @Override
    public R ttl(String key, String cacheEnv) {
        Long time = getRedisTemplate(cacheEnv).getExpire(key);
        return R.ok().data("存活时间/秒: " + time);
    }


    /*************** ===私有方法=== ********************* ===start=== ***************************************/

    private Object get(String key, String cacheEnv) {
        try {
            Serializable value = myCacheService.getRedisMasterSlaveTemplate().opsForValue().get(key);
            if (null == value) {
                return null;
            }
            String unZipVal = ZipUtil.gunzip(value.toString());
            return unZipVal;
        } catch (Exception e) {
            Map<String, Object> opParams = InstanceUtil.newHashMap(1);
            opParams.put("key", key);
            log.error(ExceptionUtil.getErrorPrintLog("从" + cacheEnv + "获取缓存", opParams, e));
            return null;
        }
    }

    private boolean delete(String key, String cacheEnv) {
        return getRedisTemplate(cacheEnv).delete(key);
    }

    private RedisTemplate<String, Serializable> getRedisTemplate(String cacheEnv) {
        if (CacheEnvConstants.REDIS_CLUSTER.equals(cacheEnv)) {
            return myCacheService.getRedisClusterTemplate();
        }
        return myCacheService.getRedisMasterSlaveTemplate();
    }
}
